<template>
  <div class="p-4 mx-auto max-w-2xl">
    <h2 class="mb-4 text-xl font-bold">图片压缩/格式转换</h2>
    
    <!-- 图片上传区域 -->
    <div 
      class="flex flex-col justify-center items-center p-6 mb-4 rounded-lg border-2 border-dashed cursor-pointer"
      :class="isDragging ? 'border-blue-500 bg-blue-50' : 'border-gray-300'"
      @dragenter.prevent="isDragging = true"
      @dragleave.prevent="isDragging = false"
      @dragover.prevent="isDragging = true"
      @drop.prevent="handleDrop($event)"
      @click="triggerFileInput"
    >
      <input 
        type="file" 
        ref="fileInput" 
        accept="image/*" 
        class="hidden"
        @change="handleFileChange"
        multiple
      />
      
      <svg xmlns="http://www.w3.org/2000/svg" class="mb-2 w-12 h-12 text-gray-400" fill="none" viewBox="0 0 24 24" stroke="currentColor">
        <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z" />
      </svg>
      
      <p class="mb-1 text-gray-700">点击或拖拽图片到此处上传</p>
      <p class="text-sm text-gray-500">支持 JPG, PNG, WebP, GIF 格式</p>
    </div>
    
    <!-- 转换选项 -->
    <div v-if="files.length > 0" class="p-4 mb-6 rounded-lg border">
      <h3 class="mb-3 font-bold">转换选项</h3>
      
      <div class="flex flex-wrap gap-4 mb-4">
        <div class="w-full md:w-auto">
          <label class="block mb-1 font-medium text-gray-700">输出格式</label>
          <select v-model="outputFormat" class="p-2 w-full rounded border">
            <option value="jpeg">JPEG</option>
            <option value="png">PNG</option>
            <option value="webp">WebP</option>
          </select>
        </div>
        
        <div class="w-full md:w-auto">
          <label class="block mb-1 font-medium text-gray-700">质量</label>
          <div class="flex items-center">
            <input 
              type="range" 
              v-model="quality" 
              min="10" 
              max="100" 
              step="5" 
              class="mr-2 w-32" 
            />
            <span>{{ quality }}%</span>
          </div>
        </div>
        
        <div class="w-full md:w-auto">
          <label class="block mb-1 font-medium text-gray-700">最大尺寸</label>
          <select v-model="maxSize" class="p-2 w-full rounded border">
            <option :value="0">原始大小</option>
            <option :value="512">512px</option>
            <option :value="1024">1024px</option>
            <option :value="1920">1920px</option>
            <option :value="2560">2560px</option>
          </select>
        </div>
      </div>
      
      <div class="flex gap-2">
        <button 
          @click="processImages" 
          class="px-4 py-2 text-white bg-blue-500 rounded"
          :disabled="isProcessing"
        >
          {{ isProcessing ? '处理中...' : '开始处理' }}
        </button>
        <button 
          @click="clearImages" 
          class="px-4 py-2 text-white bg-gray-500 rounded"
        >
          清空图片
        </button>
      </div>
    </div>
    
    <!-- 文件列表 -->
    <div v-if="files.length > 0" class="mb-6">
      <h3 class="mb-2 font-bold">图片列表</h3>
      
      <div class="rounded-lg border divide-y">
        <div 
          v-for="(file, index) in files" 
          :key="index"
          class="flex flex-wrap gap-3 items-center p-3 md:flex-nowrap"
        >
          <!-- 预览图 -->
          <div class="flex-shrink-0 w-20 h-20 bg-gray-100 rounded">
            <img 
              v-if="file.preview" 
              :src="file.preview" 
              class="object-contain w-full h-full" 
              alt="Preview"
            />
          </div>
          
          <!-- 文件信息 -->
          <div class="flex-grow">
            <div class="font-medium">{{ file.name }}</div>
            <div class="text-sm text-gray-500">{{ formatSize(file.size) }}</div>
            <div v-if="file.processed" class="mt-1">
              <span class="font-medium text-green-600">处理完成: </span>
              <span class="text-sm">{{ formatSize(file.outputSize) }} (减少 {{ calculateReduction(file) }}%)</span>
            </div>
            <div v-if="file.error" class="mt-1 text-sm text-red-500">
              {{ file.error }}
            </div>
          </div>
          
          <!-- 操作按钮 -->
          <div class="flex gap-2">
            <button 
              v-if="file.processed" 
              @click="downloadImage(file)"
              class="px-3 py-1 text-sm text-white bg-green-500 rounded"
            >
              下载
            </button>
            <button 
              @click="removeImage(index)"
              class="px-3 py-1 text-sm text-white bg-red-500 rounded"
            >
              移除
            </button>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted } from 'vue'

// 状态变量
const fileInput = ref(null)
const isDragging = ref(false)
const files = ref([])
const outputFormat = ref('jpeg')
const quality = ref(80)
const maxSize = ref(0)
const isProcessing = ref(false)

// 触发文件选择
function triggerFileInput() {
  fileInput.value.click()
}

// 处理文件选择
function handleFileChange(event) {
  addFiles(event.target.files)
  event.target.value = null // 重置input以允许选择相同文件
}

// 处理拖放
function handleDrop(event) {
  isDragging.value = false
  addFiles(event.dataTransfer.files)
}

// 添加文件到列表
function addFiles(fileList) {
  for (let i = 0; i < fileList.length; i++) {
    const file = fileList[i]
    
    // 验证是否为图片
    if (!file.type.match('image.*')) {
      continue
    }
    
    // 创建文件预览
    const reader = new FileReader()
    reader.onload = (e) => {
      files.value.push({
        file,
        name: file.name,
        size: file.size,
        type: file.type,
        preview: e.target.result,
        processed: false
      })
    }
    reader.readAsDataURL(file)
  }
}

// 处理图片压缩和转换
function processImages() {
  if (files.value.length === 0) return
  
  isProcessing.value = true
  
  const promises = files.value.map((fileItem, index) => {
    return new Promise((resolve) => {
      const img = new Image()
      img.onload = function() {
        try {
          // 计算新尺寸，保持宽高比
          let width = img.width
          let height = img.height
          
          if (maxSize.value > 0 && (width > maxSize.value || height > maxSize.value)) {
            if (width > height) {
              height = Math.round(height * (maxSize.value / width))
              width = maxSize.value
            } else {
              width = Math.round(width * (maxSize.value / height))
              height = maxSize.value
            }
          }
          
          // 创建画布
          const canvas = document.createElement('canvas')
          canvas.width = width
          canvas.height = height
          
          // 绘制调整大小后的图像
          const ctx = canvas.getContext('2d')
          ctx.drawImage(img, 0, 0, width, height)
          
          // 转换为指定格式
          let mimeType
          switch (outputFormat.value) {
            case 'jpeg': mimeType = 'image/jpeg'; break
            case 'png': mimeType = 'image/png'; break
            case 'webp': mimeType = 'image/webp'; break
            default: mimeType = 'image/jpeg'
          }
          
          // 导出图片
          canvas.toBlob(
            (blob) => {
              if (blob) {
                // 更新文件状态
                files.value[index].processedBlob = blob
                files.value[index].outputSize = blob.size
                files.value[index].processed = true
                files.value[index].outputFormat = outputFormat.value
                files.value[index].outputUrl = URL.createObjectURL(blob)
              } else {
                files.value[index].error = '处理失败'
              }
              resolve()
            },
            mimeType,
            quality.value / 100
          )
        } catch (e) {
          files.value[index].error = `处理错误: ${e.message}`
          resolve()
        }
      }
      
      img.onerror = function() {
        files.value[index].error = '图片加载失败'
        resolve()
      }
      
      img.src = fileItem.preview
    })
  })
  
  Promise.all(promises).then(() => {
    isProcessing.value = false
  })
}

// 下载处理后的图片
function downloadImage(file) {
  if (!file.processedBlob) return
  
  const a = document.createElement('a')
  a.href = file.outputUrl
  
  // 生成文件名
  const originalName = file.name
  const extension = `.${file.outputFormat}`
  const baseName = originalName.substring(0, originalName.lastIndexOf('.'))
  a.download = `${baseName}_compressed${extension}`
  
  document.body.appendChild(a)
  a.click()
  document.body.removeChild(a)
}

// 移除图片
function removeImage(index) {
  const file = files.value[index]
  if (file.outputUrl) {
    URL.revokeObjectURL(file.outputUrl)
  }
  files.value.splice(index, 1)
}

// 清空所有图片
function clearImages() {
  // 释放创建的对象URL
  files.value.forEach(file => {
    if (file.outputUrl) {
      URL.revokeObjectURL(file.outputUrl)
    }
  })
  files.value = []
}

// 格式化文件大小
function formatSize(bytes) {
  if (bytes === 0) return '0 B'
  
  const k = 1024
  const sizes = ['B', 'KB', 'MB', 'GB']
  const i = Math.floor(Math.log(bytes) / Math.log(k))
  
  return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]
}

// 计算减少的文件大小百分比
function calculateReduction(file) {
  if (!file.processed || file.size === 0) return 0
  
  const reduction = ((file.size - file.outputSize) / file.size) * 100
  return Math.round(reduction)
}
</script> 